#pragma once

#include <iostream>
#include <fstream>
#include <thread>
#include <mutex>
#include <queue>
#include <condition_variable>
#include <QString>

class outputImpl
{
public:
    outputImpl() {
        dataLog_ = std::ofstream("log.txt");
        workTh_ = std::thread(&outputImpl::launchTh, this);
    }

    ~outputImpl() {
        stopTh();
        dataLog_.close();
        workTh_.join();
    }

    void launchTh() {
        while (isRunning_) {
            QString data;
            {
                std::unique_lock<std::mutex> lock(mtx_);
                mCv_.wait(lock, [this] { return !mDatas_.empty() || !isRunning_; } );
                if (isRunning_) {
                    data = mDatas_.front();
                    mDatas_.pop_front();
                }
            }

            if (isRunning_) {
                dataLog_ << data.toStdString() << "\n";
                std::cout << __FUNCTION__ << ": " << data.toStdString() << "\n";
            }
        }
    }

    void push_back_msg(const QString &msg)
    {
        std::lock_guard<std::mutex> locker(mtx_);
        mDatas_.emplace_back(msg);
        mCv_.notify_one();
    }

    void stopTh() {
        isRunning_ = false;
        mCv_.notify_one();
    }

protected:
    bool isRunning_ = true;
    std::deque<QString> mDatas_;
    std::thread workTh_;
    std::mutex mtx_;
    std::condition_variable mCv_;
    std::ofstream dataLog_;
};
